import { OnModuleInit } from '@nestjs/common';
import { WebSocket, WebSocketServer } from 'ws';
import { join, resolve } from 'path';
import { createReadStream } from 'fs';
import { rejects } from 'assert';
import * as dayjs from 'dayjs'
export class WebsocketGateway implements OnModuleInit {
  private wss: WebSocketServer;
  private clients: Set<WebSocket> = new Set();
  // 存储客户端心跳状态
  private heartbeatStatus: Map<WebSocket, { lastBeat: number }> = new Map();
  // 心跳检查间隔 (毫秒)
  private readonly HEARTBEAT_INTERVAL = 30000;
  // 心跳超时时间 (毫秒)
  private readonly HEARTBEAT_TIMEOUT = 60000;
  private logContent: any;
  private startLine: number = 0;
  private endLine: number = 20;
  // ping测试定时器
  private pingTimer: any = null;
  private iperfTimer: any = null;
  private clientCounters: Map<
    WebSocket,
    {
      apIndex: number;
      cpIndex: number;
      kernelIndex: number;
    }
  > = new Map();
  // 服务端定时器
  private serverTimer:any = null
  private clientTimer:any = null
  onModuleInit() {
    this.wss = new WebSocket.Server({ port: 8080 });
    this.wss.on('connection', (ws: WebSocket) => {
      // 添加新连接的客户端
      this.clients.add(ws);
      // 初始化心跳状态
      this.heartbeatStatus.set(ws, { lastBeat: Date.now() });
      console.log('Client connected');
      // 处理接收到的消息
      ws.on('message', (message: string) => {
        try {
          const data = JSON.parse(message.toString());
          // 更新心跳时间
          this.updateHeartbeat(ws);
          this.handleMessage(ws, data);
        } catch (error) {
          console.error('Error parsing message:', error);
        }
      });

      // 处理客户端断开连接
      ws.on('close', () => {
        this.clients.delete(ws);
        this.heartbeatStatus.delete(ws);
        this.clientCounters.delete(ws);
        
        // 清除该客户端的定时器
        if (ws['messageIntervalId']) {
          clearInterval(ws['messageIntervalId']);
        }
        
        console.log('Client disconnected');
      });

      // 处理错误
      ws.on('error', (error) => {
        console.error('WebSocket error:', error);
      });

      // 初始化建立连接
      this.startSendingMessages(ws);
    });
    // 启动心跳检测
    this.startHeartbeatCheck();
  }

  // 建立连接后发送消息
  private startSendingMessages(ws: WebSocket) {
    // 初始化该客户端的计数器
    this.clientCounters.set(ws, {
      apIndex: 0,
      cpIndex: 0,
      kernelIndex: 0,
    });

    // 使用定时器而非递归
    const intervalId = setInterval(() => {
      if (!this.clients.has(ws)) {
        clearInterval(intervalId);
        this.clientCounters.delete(ws);
        return;
      }

      this.sendMessage(ws);
     /*  if ((this.clientCounters.get(ws).apIndex %5) === 0) {
        ws.close();
      } */
    }, 3000);

    // 立即发送第一条消息
    this.sendMessage(ws);
    setTimeout(() => {
      ws.send(
        JSON.stringify({
          cmd: 'server-done',
        }),
      );
      ws.send(
        JSON.stringify({
          cmd: 'ping-done',
        }),
      );
      clearInterval(this.serverTimer);
      clearInterval(this.pingTimer);
    }, 15000);
    // 存储定时器ID以便在连接关闭时清除
    ws['messageIntervalId'] = intervalId;
  }

  private sendMessage(ws: WebSocket) {
    // 获取该客户端的计数器
    const counters = this.clientCounters.get(ws);
    if (!counters) return;

    const payload4 = {
      cmd:"log_get",
      data:{
        type:4,
        msg: `fnjakifa_ap_${counters.apIndex}\nfnjakifa_ap_${counters.apIndex}\n
        `,
      }
    }
    const arr = [1,2]
    const id = arr[Math.floor(Math.random() * arr.length)]
    const payload7 = {
      cmd:"log_get",
      data:{
        type:7,
        id:id,
        msg: `#${id}Aug 25 19:49:06 cscn-device ap_server: (INFO): [ALL:|cp0_conv:]:[A:I] () ###0.000000 tod 2778LST.1PPS=0,0LST.loc=0.000 0.000 0.000#015#012 @[cp_log.c:55]`,
      }
    }
 
    const payload1 = {
      cmd:"log_get",
      data:{
        type:1,
        msg: `fnjakifa_ap_${counters.apIndex}\nfnjakifa_ap_${counters.apIndex}\n
        `,
      }
    }

    ws.send(Buffer.from(JSON.stringify(payload4)));

    ws.send(Buffer.from(JSON.stringify(payload7)));

    ws.send(Buffer.from(JSON.stringify(payload1)));
 
      ws.send(
        JSON.stringify({
          cmd: 'ap_ant_manage_get',
          data: { 
            ant:this.setCommInfo(),
          },
        }),
      );

      ws.send(
        JSON.stringify({
          cmd: 'ap_sync_sate_get',
          data: { 
            sate:this.sate,
          },
        }),
      );

      ws.send(
        JSON.stringify({
          cmd: 'ap_sync_lon_store_get',
          data: { 
            lon_store:this.lonStore,
          },
        }),
      );

      ws.send(
        JSON.stringify({
          cmd: 'ap_net_dnn_get',
          data: { 
            list:this.dnnInfo,
          },
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_tod_status',
          data: { 
            info:this.getTodStatusData(),
          },
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_hw_ap_info',
          data: this.setApInfo()
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_system_ap_version_cur_get',
          data: this.apList[0]
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_system_get_baseband_info',
          data: {
            info: this.info,
          },
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_sync_state',
          data: {            
            state: this.status[Math.floor(Math.random() * this.status.length)],
            ka_init_state: this.kaInitStateStatus[Math.floor(Math.random() * this.kaInitStateStatus.length)]
          }
        }),
      );

      ws.send(
        JSON.stringify({
          cmd: 'ap_system_cp_firmware_cur_get',
          data: {
            name: this.currentCpFirmware.name,
          },
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_system_cp_device_info',
          data: this.cpDeviceInfo,
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_eph_sib2_get',
          data: this.sib2_data,
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_net_host_speed_get',
          data: {
            speed_list:this.setSpeedList(),
          },
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_license_check_active',
          data: this.licenseInfo
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_ant_status_get',
          data:{
            state:this.setAntennaStatus()
          }
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_ant_phased_array_status',
          data:{
            ant:this.antStatus
          }
        }),
      )

      ws.send(
        JSON.stringify({
          cmd: 'ap_ant_fault_status',
          data:this.faultStatus
        }),
      )

    // 递增计数器
    counters.apIndex++;
    counters.cpIndex++;
    counters.kernelIndex++;
  }

  setSpeedList(){
    this.speed_list.forEach(item => {
      item.tx_bytes_ps = Math.floor(Math.random() * 10000)
      item.rx_bytes_ps = Math.floor(Math.random() * 10000)
    })
    return this.speed_list
  }

  setAntennaStatus(){
    this.antennaStatusIndex++
    if(this.antennaStatusIndex%2===0){
      this.antennaStatus[0].status = 'on'
      this.antennaStatus[1].status = 'off'
    }else{
      this.antennaStatus[0].status = 'off'
      this.antennaStatus[1].status = 'on'
    }
    return this.antennaStatus
  }

  private faultStatus = {
    attitude: 'normal',
    location: 'string',
    time_service: 'string',
    fan: 'string',
    temp_0: 'string',
    temp_1: 'string',
    temp_2: 'string',
    emission_current_1: 'string',
    emission_current_2: 'string',
    receive_current_1: 'string',
    receive_current_2: 'string',
    receive_current_3: 'string',
    receive_current_4: 'string',
    voltage_1: 'string',
    voltage_2: 'string',
    voltage_3: 'string',
    voltage_4: 'string',
  };

  private antStatus = [
    {
    buc_warn: 'abnormal',
    bdc_warn: 'abnormal',
    temp: 'string',
    inertial_navigate_warn: 'abnormal',
    overtemp_warn: 'abnormal',
    transmit_front_status_1: 'abnormal',
    transmit_front_status_2: 'abnormal',
    transmit_front_status_3: 'abnormal',
    transmit_front_status_4: 'abnormal',
    receive_front_status_1: 'abnormal',
    receive_front_status_2: 'abnormal',
    receive_front_status_3: 'abnormal',
    receive_front_status_4: 'abnormal',
    },
    {
    buc_warn: 'abnormal',
    bdc_warn: 'abnormal',
    temp: 'string',
    inertial_navigate_warn: 'abnormal',
    overtemp_warn: 'abnormal',
    transmit_front_status_1: 'abnormal',
    transmit_front_status_2: 'abnormal',
    transmit_front_status_3: 'abnormal',
    transmit_front_status_4: 'abnormal',
    receive_front_status_1: 'abnormal',
    receive_front_status_2: 'abnormal',
    receive_front_status_3: 'abnormal',
    receive_front_status_4: 'abnormal',
    }
  ]
  private antennaStatusIndex = 0;

  public antennaStatus = [
    {
      id: 0,
      status: 'on',
    },
    {
      id: 1,
      status: 'off',
    },
  ];

  public licenseInfo:any= {
    status:"failed",
    hwid:"1234567890",
  }

  public speed_list = [
    {
      name: 'private_net_dnn1',
      tx_bytes_ps:Math.floor(Math.random() * 10000),
      rx_bytes_ps: Math.floor(Math.random() * 10000),
      tx_pkt_ps: '',
      rx_pkt_ps: '',
      update_timestamp: 0,
    },
    {
      name: 'language_dnn2',
      tx_bytes_ps: Math.floor(Math.random() * 10000),
      rx_bytes_ps:Math.floor(Math.random() * 10000),
      tx_pkt_ps: '',
      rx_pkt_ps: '',
      update_timestamp: 0,
    },
    {
      name: 'internet_dnn3',
      tx_bytes_ps: Math.floor(Math.random() * 10000),
      rx_bytes_ps: Math.floor(Math.random() * 10000),
      tx_pkt_ps: '',
      rx_pkt_ps: '',
      update_timestamp: 0,
    },
    {
      name: 'xwtj_dnn4',
      tx_bytes_ps: Math.floor(Math.random() * 10000),
      rx_bytes_ps: Math.floor(Math.random() * 10000),
      tx_pkt_ps: '',
      rx_pkt_ps: '',
      update_timestamp: 0,
    },
    {
      name: 'caa_dnn5',
      tx_bytes_ps:Math.floor(Math.random() * 10000),
      rx_bytes_ps:Math.floor(Math.random() * 10000),
      tx_pkt_ps: '',
      rx_pkt_ps: '',
    },
  ]

  private sib2_data  = {
    sib2:1
  }

  private cpDeviceInfo = {
    info: [
      {
        name: 'heap1',
        total: '8388608',
        avail: '3128464',
      },
      {
        name: 'mempoo1',
        total: '8388608',
        avail: '128264',
        block: '20',
      },
      {
        name: 'mempoo2',
        total: '8388208',
        avail: '128264',
        block: '20',
      },
      {
        name: 'mempoo3',
        total: '8388308',
        avail: '5128434',
        block: '32',
      },
      {
        name: 'mempoo4',
        total: '8388208',
        avail: '128264',
        block: '20',
      },
      {
        name: 'mempoo5',
        total: '8388208',
        avail: '128264',
        block: '20',
      },
      {
        name: 'mempoo6',
        total: '8388208',
        avail: '128264',
        block: '20',
      },
      {
        name: 'mempoo7',
        total: '8388208',
        avail: '128264',
        block: '20',
      },
      
      
    ],
  };

  public cpFirmwareList: any[] = [
    {
      name: 'cp1',
      timestamp: Math.floor(new Date().getTime() / 1000),
    },
    {
      name: 'cp2',
      timestamp: Math.floor(new Date().getTime() / 1000),
    },
    {
      name: 'cp3',
      timestamp: Math.floor(new Date().getTime() / 1000),
    },
  ];
  public currentCpFirmware: any = this.cpFirmwareList[0];
  public status: number[] = [0,1,2,3,4,5,6,7]
  private kaInitStateStatus:number[]=[0,1,2]
  private info = [
    {
      id: 0,
      name: '基带1',
      status: 'success',
      ip: '192.168.1.1',
      bool: true,
      devinfo: {
        config: 'lowrail',
        version: 'Device not connected',
        board_temer_temper: 80,
      },
    },
    {
      id: 1,
      name: '基带2',
      status: 'success',
      ip: '192.168.1.2',
      bool: false,
      devinfo: {
        config: 'lowrail',
        version: 'Device not connected',
        board_temer_temper: 80,
      },
    },
  ];

  public apList: any[] = [
    {
      index: 0,
      version: 'string',
    },
    {
      index: 1,
      version: 'string',
    },
    {
      index: 2,
      version: 'string',
    },
  ];
  public apInfo = {
    cpu_usage: Math.floor(Math.random() * 301) - 100,
    memory_usage: Math.floor(Math.random() * 301) - 100,
    disk_usage: Math.floor(Math.random() * 301) - 100
  }

  setApInfo(){
    this.apInfo.cpu_usage = Math.floor(Math.random() * 301) - 100
    this.apInfo.memory_usage = Math.floor(Math.random() * 301) - 100
    this.apInfo.disk_usage = Math.floor(Math.random() * 301) - 100
    return this.apInfo
  }


  async setLogContent() {
    try {
      const filePath = join(process.cwd(), 'public/app.log');
      this.logContent = await new Promise<string>((resolve, reject) => {
        let data = '';
        const fileStream = createReadStream(filePath, 'utf8');
        fileStream.on('data', (chunk) => {
          data += chunk;
        });
        fileStream.on('end', () => {
          resolve(data);
        });
        fileStream.on('error', (error) => {
          reject(error);
        });
      });
    } catch (error) {}
  }

  getIncrementalLog() {
    let list = this.logContent
      .split('\n')
      .slice(this.startLine, this.endLine)
      .join('\n');
    this.startLine = this.endLine;
    this.endLine = this.endLine + 20;
    return list;
  }

  // 更新客户端心跳时间
  private updateHeartbeat(client: WebSocket): void {
    const status = this.heartbeatStatus.get(client);
    if (status) {
      status.lastBeat = Date.now();
    }
  }

  // 启动心跳检测
  private startHeartbeatCheck(): void {
    setInterval(() => {
      const now = Date.now();
      this.heartbeatStatus.forEach((status, client) => {
        // 检查客户端是否超时
        if (now - status.lastBeat > this.HEARTBEAT_TIMEOUT) {
          console.log('Client heartbeat timeout, closing connection');
          client.terminate(); // 强制关闭连接
          this.clients.delete(client);
          this.heartbeatStatus.delete(client);
        }
      });
    }, this.HEARTBEAT_INTERVAL);
  }

  getTodStatusData() {
    return {
      tod_sec: dayjs().unix().toString().toString(),
      tod_usec: 1702212000000000,
      longitude: -118.2437,
      latitude: 160,
      altitude: 22.01,
      eastward_speed: 22.01,
      northward_speed: 22.01,
      skyward_speed: 22.01,
    };
  }

  public num:number=0
  setCommInfo(){
    this.num++
     this.commInfo.forEach(item => {
      item.status.status = this.num % 2 === 0 ? 'on' : 'off'
     })
     return this.commInfo
  }

  public commInfo: any = [
    {
      id: 0,
      status: {
        id: 0,
        // 双数on,偶数off
        mode: this.num % 2 === 0 ? 'on' : 'off',
        status: 'on',
        buc_warn: 'abnormal',
        bdc_warn: 'abnormal',
        type: '0.9double_paraboloid',
        temp: 0,
        elevate: 0,
        azimuth: 0,
        inertial_navigate_warn: 'abnormal',
        overtemp_warn: 'abnormal',
        transmit_front_status_1: 'abnormal',
        transmit_front_status_2: 'abnormal',
        transmit_front_status_3: 'abnormal',
        transmit_front_status_4: 'abnormal',
        receive_front_status_1: 'abnormal',
        receive_front_status_2: 'abnormal',
        receive_front_status_3: 'abnormal',
        receive_front_status_4: 'abnormal',
        ss: 80,
        sinr: 90,
        sat:50,
      },
      param: {
        id: 0,
        transmit_switch: 'on',
        receive_switch: 'on',
        track_switch: 'on',
        transmit_frequency: 22500,
        receive_frequency: 22500,
        transmit_polarization: 'right',
        receive_polarization: 'right',
        buc: "15.00",
        bdc: "0.00",
      },
      communication: {
        id: 0,
        name: 'ant1',
        ip_addr: '192.168.1.2',
        ip_port: 8080,
        local_port: 6665,
        serial_name: 'ttyS0',
        serial_baud: 115200,
        enable: 'on',
        status: 'on',
        cp_device:"cp1"
      },
      kd:"可动11111111"
    },
    {
      id: 1,
      status: {
        id: 0,
        mode: 'on',
        status: 'off',
        buc_warn: 'abnormal',
        bdc_warn: 'abnormal',
        type: '0.9double_paraboloid',
        temp: 0,
        elevate: 0,
        azimuth: 0,
        inertial_navigate_warn: 'abnormal',
        overtemp_warn: 'abnormal',
        transmit_front_status_1: 'abnormal',
        transmit_front_status_2: 'abnormal',
        transmit_front_status_3: 'abnormal',
        transmit_front_status_4: 'abnormal',
        receive_front_status_1: 'abnormal',
        receive_front_status_2: 'abnormal',
        receive_front_status_3: 'abnormal',
        receive_front_status_4: 'abnormal',
        ss: 80,
        sinr: 90,
        sat:50,
      },
      param: {
        id: 0,
        transmit_switch: 'on',
        receive_switch: 'on',
        track_switch: 'on',
        transmit_frequency: 22500,
        receive_frequency: 22500,
        transmit_polarization: 'right',
        receive_polarization: 'right',
        buc: "15.00",
        bdc: "0.00",
      },
      communication: {
        id: 0,
        name: 'ant1',
        ip_addr: '192.168.1.2',
        ip_port: 8080,
        local_port: 6665,
        serial_name: 'ttyS0',
        serial_baud: 115200,
        enable: 'on',
        status: 'on',
        cp_device:"cp2"
      },
      kd:"可动222222"
    },
  ];
  public dnnInfo: any = [
    {
      id: 2,
      name: 'private_net_dnn1',
      type: 'private_net',
      portmap: "3",
      dnn_ip: '192.168.10.110.192.168.10.110.192.168.10.110',
      dhcp_relay: 'on',
      dhcp_start_ip: '192.168.10.100',
      dhcp_end_ip: '192.168.10.254',
      dhcp_dns1: '8.8.8.8',
      dhcp_dns2: '114.114.114.114',
      dhcp_gw: '192.168.10.1',
      dhcp_mask: '255.255.255.0',
      dnn_status: 0,
      connect: 'on',
      lan_ip: '192.168.10.1',
      vlan_id: 10,
      nat_status: 'off',
      local_status: 'off',
      using_dnn: 'private_net_dnn1',
      dhcp_status: 'off',
    },

    {
      id: 1,
      name: 'language_dnn2',
      type: 'language',
      portmap: "7",
      dnn_ip: '192.168.10.110.192.168.10.110.192.168.10.110',
      dhcp_relay: 'on',
      dhcp_start_ip: '192.168.10.100',
      dhcp_end_ip: '192.168.10.254',
      dhcp_dns1: '8.8.8.8',
      dhcp_dns2: '114.114.114.114',
      dhcp_gw: '192.168.10.1',
      dhcp_mask: '255.255.255.0',
      dnn_status: 0,
      connect: 'on',
      lan_ip: '192.168.10.1',
      vlan_id: 10,
      nat_status: 'on',
      local_status: 'on',
      using_dnn: 'language_dnn2',
      dhcp_status: 'off',
    },
    {
      id: 4,
      name: 'xwtj_dnn4',
      type: 'xwtj',
      portmap: "5",
      dnn_ip: '192.168.10.110.192.168.10.110.192.168.10.110',
      dhcp_relay: 'on',
      dhcp_start_ip: '192.168.10.100',
      dhcp_end_ip: '192.168.10.254',
      dhcp_dns1: '8.8.8.8',
      dhcp_dns2: '114.114.114.114',
      dhcp_gw: '192.168.10.1',
      dhcp_mask: '255.255.255.0',
      dnn_status: 0,
      connect: 'on',
      lan_ip: '192.168.10.1',
      vlan_id: 10,
      nat_status: 'on',
      local_status: 'off',
      using_dnn: 'xwtj_dnn4',
      dhcp_status: 'on',
    },
    {
      id: 3,
      name: 'internet_dnn3',
      type: 'internet',
      portmap: "8",
      dnn_ip: '192.168.10.110.192.168.10.110.192.168.10.110',
      dhcp_relay: 'on',
      dhcp_start_ip: '192.168.10.100',
      dhcp_end_ip: '192.168.10.254',
      dhcp_dns1: '8.8.8.8',
      dhcp_dns2: '114.114.114.114',
      dhcp_gw: '192.168.10.1',
      dhcp_mask: '255.255.255.0',
      dnn_status: 0,
      connect: 'on',
      lan_ip: '192.168.10.1',
      vlan_id: 10,
      nat_status: 'on',
      local_status: 'off',
      using_dnn: 'internet_dnn3',
      dhcp_status: 'off',
    },
    {
      id: 5,
      name: 'caa_dnn5',
      type: 'caa',
      portmap: "3",
      dnn_ip: '192.168.10.110.192.168.10.110.192.168.10.110',
      dhcp_relay: 'on',
      dhcp_start_ip: '192.168.10.100',
      dhcp_end_ip: '192.168.10.254',
      dhcp_dns1: '8.8.8.8',
      dhcp_dns2: '114.114.114.114',
      dhcp_gw: '192.168.10.1',
      dhcp_mask: '255.255.255.0',
      dnn_status: 0,
      connect: 'on',
      lan_ip: '192.168.10.1',
      vlan_id: 10,
      nat_status: 'off',
      local_status: 'off',
      using_dnn: 'caa_dnn5',
      dhcp_status: 'on',
    }
    
  ];
  private lonStore: number = Math.floor(Math.random() * 200)
  public sate: number=1
  // 处理接收到的消息
  private async handleMessage(client: WebSocket, data: any) {
    console.log('Received message:', data);
    // 处理心跳消息
    if (data.command === 'heartbeat') {
      client.send(
        JSON.stringify({
          cmd: 'heartbeat',
        }),
      );
      return;
    }
    switch (data.command) {
      case 'ping-stop':
        clearInterval(this.pingTimer);
        client.send(
          JSON.stringify({
            cmd: 'ping-stop',
            data: {
              msg: 'success',
            },
          }),
        );
        clearInterval(this.pingTimer);
        break;
      case 'iperf-start':
        if(data.data.direction === 'server'){
          this.serverTimer = setInterval(() => {
            client.send(
              JSON.stringify({
                cmd: 'server',
                data:{
                  msg:'server'+new Date().getTime(),
                }
              }),
            );
          }, 5000);
        }else{
          this.clientTimer = setInterval(() => {
            client.send(
              JSON.stringify({
                cmd: 'client',
                data:{
                  msg:'client'+new Date().getTime(),
                }
              }),
            );
          }, 5000);
        }
        break;
      case 'iperf-stop':
        data.data.direction === 'server' ? clearInterval(this.serverTimer) : clearInterval(this.clientTimer)
        client.send(
          JSON.stringify({
            cmd: 'iperf-stop',
            data: {
              msg: 'success',
            },
          }),
        );
        break;
      case 'ping-start':
        this.pingTimer = setInterval(() => {
          client.send(
            JSON.stringify({ cmd: 'ping', data: { msg: new Date().getTime() } }),
          );
        }, 5000);     
    }
  }

  // 广播消息给所有客户端
  public broadcast(message: any) {
    this.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(
          JSON.stringify({
            type: 'broadcast',
            message,
          }),
        );
      }
    });
  }

  // 发送消息给特定客户端
  public sendTo(client: WebSocket, message: any) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(JSON.stringify(message));
    }
  }
}
